package com.tenthoundsqps.service;

import com.tenthoundsqps.dao.OrderDao;
import com.tenthoundsqps.entity.Order;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;

/**
 * 订单归档服务类
 * 实现冷热数据分离功能
 * 
 * 冷热数据分离策略：
 * 1. 热数据：最近3个月的订单，存储在主订单表中
 * 2. 冷数据：3个月前的订单，归档到历史订单表中
 * 
 * 归档机制：
 * 1. 定时任务每天凌晨执行
 * 2. 批量处理避免对数据库造成过大压力
 * 3. 归档后前端通过不同入口查询
 */
@Service
public class ArchiveService {
    
    private static final Logger logger = LoggerFactory.getLogger(ArchiveService.class);
    
    /**
     * 订单数据访问对象
     */
    @Autowired
    private OrderDao orderDao;
    
    /**
     * 定时归档3个月前的订单数据
     * 每天凌晨2点执行，避免业务高峰期
     * 
     * 归档流程：
     * 1. 查询创建时间早于3个月前且未归档的订单
     * 2. 分批处理避免对数据库造成过大压力
     * 3. 将订单标记为已归档状态
     */
    @Scheduled(cron = "0 0 2 * * ?")
    public void archiveOldOrders() {
        logger.info("Starting archive old orders job");
        
        // 计算3个月前的时间作为归档时间阈值
        LocalDateTime archiveTime = LocalDateTime.now().minusMonths(3);
        // 每批处理的订单数量
        int batchSize = 1000;
        // 总归档订单数统计
        int totalArchived = 0;
        
        try {
            List<Order> ordersToArchive;
            do {
                // 分批查询需要归档的订单
                // 避免一次性查询大量数据导致内存溢出
                ordersToArchive = orderDao.selectOrdersToArchive(archiveTime, batchSize);
                
                // 执行归档操作
                for (Order order : ordersToArchive) {
                    // 将订单标记为已归档
                    int result = orderDao.archiveOrder(order.getId());
                    if (result > 0) {
                        totalArchived++;
                    }
                }
                
                logger.info("Archived {} orders in current batch", ordersToArchive.size());
                
                // 用户提出的问题非常好：为什么是 == 而不是 <？
                // 原始逻辑分析：
                // while (ordersToArchive.size() == batchSize)
                // 
                // 这个逻辑的正确性分析：
                // 1. 当查询到完整一批数据时（size == batchSize），说明可能还有更多数据，继续循环
                // 2. 当查询到不完整一批数据时（size < batchSize），说明是最后一批或没有更多数据了，结束循环
                //
                // 举例说明执行过程：
                // 假设总共有2500条符合条件的数据，batchSize=1000
                // 第1次查询：得到1000条数据，1000 == 1000，继续循环
                // 第2次查询：得到1000条数据，1000 == 1000，继续循环
                // 第3次查询：得到500条数据，500 != 1000，结束循环
                //
                // 所以原始逻辑是正确的。用户的疑问让我们更深入地理解了代码的设计意图。
            } while (ordersToArchive.size() == batchSize);
            
            logger.info("Archive job completed. Total archived orders: {}", totalArchived);
            
        } catch (Exception e) {
            logger.error("Error occurred during archiving orders", e);
        }
    }
}